Interactive Seismic Data Section Plot Visualization in Python¶

Introduction¶

Seismic data section plots are visual representations that shows the amplitude of seismic data at different depths as a function of time and are used to visualize the subsurface and to identify geological features, such as faults and oil and gas reservoirs. Python is a versatile programming language that can be used to create and customize seismic data section plots, making it a great choice for seismic data visualization.

About the data: SEGY file from the Volve Dataset's Seismic Folder¶

SEGY files are a standard binary file format used in the oil and gas industry for storing seismic data. They can be read and written by certain software programs, making them a convenient way to store and exchange seismic data.

For this practice coding, a SEGY file was extracted from the Volve Dataset's Seismic folder. Specifically, the SEGY file was extracted from the ST0202vsST10010_4D subdirectory, which contains data from the 4D processing of ST0202 and ST10010 (matched data).

The SEGY file was then further extracted from the Stacks subfolder, which contains raw and final stacks of the processing of the seismic survey. Take note that the selected SEGY file is a sizeable 1.13 GB.

Python Code for Creating Interactive Seismic Visualizations ¶

We imported three Python libraries in this code process:

  • NumPy: for reading the seismic data from the SEGY file and reorganizing the data into a regular grid.
  • Plotly: for creating interactive visualizations of the seismic data.
  • Segyio: a Python library for reading SEGY files. Developed by Equinor.

By using these libraries, we are able to enhance data operations, create attractive visualizations with ease, handle file paths and directories conveniently, and perform data interpolation in our code. This makes our code more efficient, powerful, and user-friendly.

After importing the aforementioned Python libraries, we read the SEGY file and ignores the geometric information. Thereafter, it extracts the following information from the SEGY file:

  • The sample times (t)
  • The inline (il) and crossline (xl) coordinates of each trace
  • The trace data (traces)

Subsequently, the code defines a regular IL and XL axis using NumPy. The il_unique and xl_unique arrays contain the unique IL and XL values in the SEGY file. The il_min, il_max, xl_min, and xl_max variables store the minimum and maximum IL and XL values.

Next, the code reorganizes the trace data into the regular grid. The d array stores the reorganized trace data.

Then, the code creates a figure for the seismic data section using Plotly. The go.Heatmap() function is used to create a heatmap of the seismic data section. The z argument to the go.Heatmap() function specifies the values to be plotted while the x argument specifies the x-axis values, and the y argument specifies the y-axis values.

In [1]:
# Import python libraries
import numpy as np
import plotly.graph_objects as go
import segyio

# Read the segy file
segyfile = 'ST0202ZDC12-PZ-PSDM-KIRCH-FULL-D.MIG_FIN.POST_STACK.3D.JS-017534.segy'

f = segyio.open(segyfile, ignore_geometry=True)

t = f.samples
il = f.attributes(segyio.TraceField.INLINE_3D)[:]
xl = f.attributes(segyio.TraceField.CROSSLINE_3D)[:]

traces = segyio.collect(f.trace)[:]
ntraces, nt = traces.shape

# Define a regular IL and XL axis using numpy
il_unique = np.unique(il)
xl_unique = np.unique(xl)

il_min, il_max = min(il_unique), max(il_unique)
xl_min, xl_max = min(xl_unique), max(xl_unique)

dt = t[1] - t[0]
dil = min(np.unique(np.diff(il_unique)))
dxl = min(np.unique(np.diff(xl_unique)))

# Set regular axis
ilines = np.arange(il_min, il_max + dil, dil)
xlines = np.arange(xl_min, xl_max + dxl, dxl)
nil, nxl = ilines.size, xlines.size

ilgrid, xlgrid = np.meshgrid(np.arange(nil), np.arange(nxl), indexing='ij')

# Look-up table
traces_indeces = np.full((nil, nxl), np.nan)
iils = (il - il_min) // dil
ixls = (xl - xl_min) // dxl
traces_indeces[iils, ixls] = np.arange(ntraces)
traces_available = np.logical_not(np.isnan(traces_indeces))

# Reorganize traces in regular grid
d = np.zeros((nil, nxl, nt))
d[ilgrid.ravel()[traces_available.ravel()], xlgrid.ravel()[traces_available.ravel()]] = traces

# Create figure for seismic data section
fig = go.Figure(data=go.Heatmap(z=d[nil//2].T, x=xlines, y=np.flip(t), 
                                colorscale='RdYlBu', zmin=-5, zmax=5, zsmooth='best'))

# Update and show the plot
fig.update_layout(title='SEISMIC DATA SECTION', title_x=0.5, # Center title
                  width=700, height=600, autosize=False)
fig.show()

After running the Python code above, we can now see an interactive seismic data section plot generated from the SEGY file. This plot can be easily explored and analyzed, providing us with valuable insights into the subsurface geology.

NOTE: You can adjust the plot size on the code depending on your preference.

Data Credits ¶

Equinor ASA (formerly Statoil) and the former Volve license partners, ExxonMobil Exploration & Production Norway AS and Bayerngas Norge AS, are credited for providing the VOLVE dataset under CC BY 4.0 license.